<template>
  <component :is="inputComponent" v-bind="{ ...compProps, ...$attrs }" v-model:value="modelValue">
    <template v-if="props.showSwitchText" #checked> {{ optionMap[1] }}</template>
    <template v-if="props.showSwitchText" #unchecked> {{ optionMap[0] }}</template>
    <template v-if="component === 'checkbox'">
      <n-checkbox v-for="opt in options" :key="opt.dictCode" :value="opt.dictCode" :label="opt.dictName" />
    </template>
    <template v-if="component === 'radio' || component === 'radioButton'">
      <template v-for="opt in options" :key="opt.dictCode">
        <component :is="component === 'radio' ? NRadio : NRadioButton" :value="opt.dictCode" :label="opt.dictName" />
      </template>
    </template>
  </component>
</template>

<script setup lang="ts">
  import { CommonApi } from '@/api/common'
  import { DictData, DictInputProps, DictInputValues } from './types'
  import { NCheckbox, NCheckboxGroup, NRadio, NRadioButton, NRadioGroup, NSelect, NSwitch, NTree, NTreeSelect } from 'naive-ui'
  import { useCacheStore } from '@/store/modules/cache'

  defineOptions({
    name: 'EDictInput'
  })

  const props = withDefaults(defineProps<DictInputProps>(), {
    multiple: false,
    component: 'select',
    showSwitchText: false,
    async: false
  })

  const modelValue = defineModel<DictInputValues>('value')

  const options = ref<DictData[]>()
  const optionMap = ref({})

  const inputComponent = ref<any>()
  const compProps = ref({})
  const cacheStore = useCacheStore()

  const dictFilter = (list: DictData[]): DictData[] => {
    if (!list) {
      return []
    }
    const temp: DictData[] = []
    list.forEach((item) => {
      if (item.isLeaf) {
        delete item.children
      } else if (item.children && item.children.length > 0) {
        item.children = dictFilter(item.children)
      }
      if (props.filter) {
        props.filter(item) && temp.push(item)
      } else {
        temp.push(item)
      }
    })
    return temp
  }

  const loadData = (params = {}) => {
    // console.log('props.queryParams --->> ', props.queryParams)
    const _params = {
      code: props.code,
      parentId: props.topPid,
      async: props.async,
      ...props.queryParams,
      ...params
    }
    const cacheKey = `dict_${Object.values(_params).join('$$')}`
    const cacheValue = cacheStore.getValue(cacheKey)
    if (cacheValue) {
      return Promise.resolve(cacheValue)
    } else {
      return new Promise<DictData[]>((resolve) => {
        CommonApi.getDicts(_params).then((resp) => {
          const value = dictFilter(resp.data)
          // console.log('loadData --->> ', value)
          // value.forEach((item) => {
          //   item.isLeaf && (item.children = undefined)
          // })
          cacheStore.setValue(cacheKey, value)
          resolve(value)
        })
      })
    }
  }

  const loadChildren = async (option?: any) => {
    option.children = await loadData({
      parentId: option.dictCode
    })
  }

  switch (props.component) {
    case 'treeSelect':
      inputComponent.value = markRaw(NTreeSelect)
      compProps.value = {
        options,
        // cascade: true,
        multiple: props.multiple,
        checkable: props.multiple,
        labelField: 'dictName',
        keyField: 'dictCode',
        childrenField: 'children',
        onLoad: loadChildren
      }
      break
    case 'tree':
      inputComponent.value = markRaw(NTree)
      compProps.value = {
        data: options,
        selectable: !props.multiple,
        blockNode: !props.multiple,
        // cascade: true,
        multiple: props.multiple,
        checkable: props.multiple,
        labelField: 'dictName',
        keyField: 'dictCode',
        childrenField: 'children',
        selectedKeys: props.multiple ? undefined : modelValue,
        checkedKeys: props.multiple ? modelValue : undefined,
        'onUpdate:checked-keys': (keys: DictInputValues) => {
          console.log('keys ---> ', keys)
          modelValue.value = keys
        },
        onLoad: loadChildren
      }
      break
    case 'checkbox':
      inputComponent.value = markRaw(NCheckboxGroup)
      break
    case 'radio':
    case 'radioButton':
      inputComponent.value = markRaw(NRadioGroup)
      break
    case 'switch':
      inputComponent.value = markRaw(NSwitch)
      compProps.value = {
        checkedValue: 1,
        uncheckedValue: 0
      }
      break
    default:
      inputComponent.value = markRaw(NSelect)
      compProps.value = {
        options,
        multiple: props.multiple,
        labelField: 'dictName',
        valueField: 'dictCode'
      }
      break
  }

  export interface EDictInputInst {
    options: DictData[]
  }

  defineExpose<EDictInputInst>({
    options: options.value || []
  })

  const emits = defineEmits<{
    (e: 'show', value?: DictInputValues, options?: DictData[]): void
  }>()

  // const component = props.component
  onMounted(async () => {
    const data = await loadData()
    options.value = data
    data.forEach((item) => {
      optionMap.value[item.dictCode] = item.dictName
    })
    emits('show', modelValue.value, options.value)
  })
</script>

<style scoped></style>
